package com.videoStream.video.service.impl;

import com.videoStream.video.cache.CacheUtil;
import com.videoStream.video.m3u8.DefaultM3u8Build;
import com.videoStream.video.m3u8.M3u8Context;
import com.videoStream.video.pojo.CameraLive;
import com.videoStream.video.pojo.CameraPojo;
import com.videoStream.video.pojo.Config;
import com.videoStream.video.rtsp.HkRtspBuild;
import com.videoStream.video.rtsp.RtspContext;
import com.videoStream.video.service.CameraService;
import com.videoStream.video.thread.CameraThread;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author: wwy
 * @Date: 2022/7/14 9:36
 */
@Service
public class CameraServiceImpl implements CameraService {
    private static final Logger LOGGER = LoggerFactory.getLogger(CameraServiceImpl.class);
    @Autowired
    private Config config;
    /**
     * 存放任务 线程
     */
    public static Map<String, CameraThread.MyRunnable> JOBMAP = new HashMap<>();

    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    /**
     * 打开监控预览
     * @param cameraPojo
     * @return
     */
    @Override
    public CameraLive openCamera(CameraPojo cameraPojo) {
        CameraLive cameraLive = new CameraLive();
        //判断该监控是否有存在的流
        Set<String> keys = CacheUtil.STREATMAP.keySet();
        //当前时间
        String openTime = simpleDateFormat.format(new Date());
        if(keys.size() == 0 ){
            //不存在，创建直播流
            cameraPojo.setOpentime(openTime);
            this.openStream(cameraPojo);
        }else{
            //校验是否存在，ip，通道 码流一致的直播流，不存在，进行创建

            // 是否存在的标志；false：不存在；true：存在
            boolean sign = false;
            for (String key : keys) {
                if(cameraPojo.getIp().equals(CacheUtil.STREATMAP.get(key).getIp()) && cameraPojo.getChannel() == CacheUtil.STREATMAP.get(key).getChannel() && cameraPojo.getStream().equals(CacheUtil.STREATMAP.get(key).getStream())){
                    //该监控流已经推送，直接获取
                    cameraPojo = CacheUtil.STREATMAP.get(key);
                    sign = true;
                    break;
                }
            }

            if(sign){
                //存在
                cameraPojo.setCount(cameraPojo.getCount() + 1);
                cameraPojo.setOpentime(openTime);
            }else{
                //不存在，打开流
                cameraPojo.setOpentime(openTime);
                this.openStream(cameraPojo);
            }

        }

        cameraLive.setToken(cameraPojo.getToken());
        cameraLive.setUrl(cameraPojo.getUrl());



        return cameraLive;
    }

    /**
     * 关流
     * @param tokens
     */
    @Override
    public void closeCamera(String tokens) {
        String[] tokenArr = tokens.split(",");
        for (String token : tokenArr) {
            if (JOBMAP.containsKey(token) && CacheUtil.STREATMAP.containsKey(token)) {
                // 回放手动关闭
                if (null != CacheUtil.STREATMAP.get(token).getStarttime()) {
                    if (0 == CacheUtil.STREATMAP.get(token).getCount() - 1) {
                        CacheUtil.PUSHMAP.get(token).setExitcode(1);
                        CacheUtil.STREATMAP.get(token).setCount(CacheUtil.STREATMAP.get(token).getCount() - 1);
                    } else {
                        CacheUtil.STREATMAP.get(token).setCount(CacheUtil.STREATMAP.get(token).getCount() - 1);
                        LOGGER.info("当前设备正在进行回放，使用人数为" + CacheUtil.STREATMAP.get(token).getCount() + " 设备信息：[ip："
                                + CacheUtil.STREATMAP.get(token).getIp() + " channel:"
                                + CacheUtil.STREATMAP.get(token).getChannel() + " stream:"
                                + CacheUtil.STREATMAP.get(token).getStream() + " statrtime:"
                                + CacheUtil.STREATMAP.get(token).getStream() + " endtime:"
                                + CacheUtil.STREATMAP.get(token).getEndtime() + " url:"
                                + CacheUtil.STREATMAP.get(token).getUrl() + "]");
                    }
                } else {
                    if (0 < CacheUtil.STREATMAP.get(token).getCount()) {
                        // 人数-1
                        CacheUtil.STREATMAP.get(token).setCount(CacheUtil.STREATMAP.get(token).getCount() - 1);
                        LOGGER.info("关闭成功 当前设备使用人数为" + CacheUtil.STREATMAP.get(token).getCount() + " 设备信息：[ip："
                                + CacheUtil.STREATMAP.get(token).getIp() + " channel:"
                                + CacheUtil.STREATMAP.get(token).getChannel() + " stream:"
                                + CacheUtil.STREATMAP.get(token).getStream() + " statrtime:"
                                + CacheUtil.STREATMAP.get(token).getStream() + " endtime:"
                                + CacheUtil.STREATMAP.get(token).getEndtime() + " url:"
                                + CacheUtil.STREATMAP.get(token).getUrl() + "]");
                    }
                }

            }
        }
    }

    /**
     * 打开流
     * @param cameraPojo
     */
    private void openStream(CameraPojo cameraPojo){
        // 生成token
        String token = UUID.randomUUID().toString();
        cameraPojo.setToken(token);
        //校验是否需要构建rtsp地址
        int buildRtspType = cameraPojo.getBuildRtspType();
        if(buildRtspType == 0){
            //系统构建
            RtspContext rtspContenxt = new RtspContext(new HkRtspBuild());
            String rtspUrl = rtspContenxt.rtspUrl(cameraPojo.getIp(),cameraPojo.getUsername(),cameraPojo.getPassword(),cameraPojo.getChannel(),cameraPojo.getStream());
            cameraPojo.setRtsp(rtspUrl);
        }
        M3u8Context m3u8Context = new M3u8Context(new DefaultM3u8Build(config.getM3u8_push_host(), cameraPojo.getIp(), config.getM3u8_push_port(), config.getM3u8_file_path()));
        String m3u8 = m3u8Context.m3u8Url();
        String m3u8FileTemplate = m3u8Context.m3u8TemplateUrl();
        String url = m3u8Context.m3u8LiveUrl();
        //生成m3u8地址
        cameraPojo.setM3u8(m3u8);
        cameraPojo.setM3u8FileTemplate(m3u8FileTemplate);
        cameraPojo.setUrl(url);
        cameraPojo.setCount(1);

        CameraThread.MyRunnable job = new CameraThread.MyRunnable(cameraPojo);
        CameraThread.MyRunnable.es.execute(job);
        JOBMAP.put(token, job);
    }

    /**
     * 网络校验
     * @param ip
     * @param port
     * @return
     */
    @Override
    public boolean networkTest(String ip,short port){
        Socket socket = new Socket();
        try {
            // 建立TCP Socket连接，超时时间1s，如果成功继续执行，否则return
            socket.connect(new InetSocketAddress(ip, port), 1000);
        } catch (IOException e) {
            return false;
        }
        return true;
    }
}
